package com.zzy.furns.filter;

import com.zzy.furns.utils.JDBCUtilsByDruid;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

public class TransactionFilter implements Filter {

    /**
     * public static final ThreadLocal<Connection> transactionConnection = new ThreadLocal<>();
     * 这里用到ThreadLocal的重要特性：一起请求对应一个线程，请求结束，线程销毁，与线程相关联的ThreadLocal也被销毁
     * 注意：上述说法理论上没错，但实际不可行
     * 原因：
     *     现代Web服务器（例如Tomcat）是使用线程池来处理HTTP请求的，
     *     这意味着当接收到HTTP请求时，Tomcat从线程池中获取一个线程来处理请求
     *     当请求结束后，该线程并不会销毁，而是重新放回到线程池中
     *     如果我们在请求结束时不执行transactionConnection.remove()将ThreadLocal对象销毁
     *     就会导致该线程始终持有该ThreadLocal变量，导致
     *     1.内存泄露：该ThreadLocal变量一直持有和线程的强引用，导致它及其引用的所有对象都无法被垃圾回收
     *     2.数据错乱：当再有HTTP请求时，如果从线程池获取到该线程，则该线程的ThreadLocal变量依然是之前的连接，可能会导致事务混乱、数据错乱的情况
     *
     *     如果只执行Connection.close() 不执行ThreadLocal.remove() 是否可行？
     *     答：不可行，因为Connection.close() 与 ThreadLocal.remove()是两个不同层面的操作
     *     Connection.close()是将数据库连接放回到连接池中，但如果没有ThreadLocal.remove()，
     *     则线程会始终持有该数据库连接connection对象，可能导致
     *     1.多个线程争夺一个数据库连接
     *     2.事务混乱
     *     3.内存泄漏
     */

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        try {
            filterChain.doFilter(servletRequest,servletResponse);
            JDBCUtilsByDruid.commitTransaction();
        } catch (Exception e) {
            JDBCUtilsByDruid.rollback();
            System.out.println("事务回滚成功");
            throw new RuntimeException(e);
        }
//        HttpServletRequest req = (HttpServletRequest) servletRequest;
//        String method = req.getParameter("action");
//
//        //只针对OrderServlet中的saveOrder方法进行事务管理
//        if (!"saveOrder".equals(method)){
//            //不是saveOrder方法 直接放行
//            filterChain.doFilter(servletRequest,servletResponse);
//            return;
//        }
//
//        //是saveOrder方法 进行事务管理
//        try {
//            //从数据库连接池中获取一个连接
//            Connection connection = JDBCUtilsByDruid.getConnection();
//            //取消自动提交
//            connection.setAutoCommit(false);
//
//            //将获取的数据库连接保存在当前线程的ThreadLocal中（一个线程可以有多个ThreadLocal）
//            transactionConnection.set(connection);
//
//            filterChain.doFilter(servletRequest,servletResponse);
//
//            //提交事务
//            connection.commit();
//        } catch (Exception e) {
//            System.out.println("捕获到异常发生===》 " + e.getMessage());
//            //回滚事务
//            try {
//                transactionConnection.get().rollback();
//                System.out.println("事务回滚成功");
//            } catch (SQLException ex) {
//                System.out.println("事务回滚异常，请手动处理数据");
//                throw new RuntimeException(ex);
//            }
//        }
    }

    @Override
    public void destroy() {

    }
}
